﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using Microsoft.Gateway.Configuration;
using Microsoft.Gateway.Utils;
using Microsoft.Web.Administration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Gateway.RulesConfigurator
{
    class WebfarmConfigurator
    {

        internal static ConfigurationElementCollection ConfigureWebFarmsNodeDefaults(Web.Administration.Configuration webConfig)
        {
            //Create Webfarm and add servers
            var webFarmsCollection = webConfig.GetSection("webFarms").GetCollection();
            webFarmsCollection.Clear();
            
            var webfarmsARR = webFarmsCollection.GetChildElement("applicationRequestRouting");
            var hostAffinityProviders = webfarmsARR.GetChildElement("hostAffinityProviderList");
            var hostAffinityProviderCollection = hostAffinityProviders.GetCollection();
            hostAffinityProviderCollection.Clear();

            var roundrobin = hostAffinityProviderCollection.CreateElement("add");
            roundrobin["name"] = "Microsoft.Web.Arr.HostNameRoundRobin";
            hostAffinityProviderCollection.Add(roundrobin);

            var hostnameMemory = hostAffinityProviderCollection.CreateElement("add");
            hostnameMemory["name"] = "Microsoft.Web.Arr.HostNameMemory";
            hostAffinityProviderCollection.Add(hostnameMemory);
            return webFarmsCollection;
        }

        internal static void CreateWebFarm(ConfigurationElementCollection webFarmsCollection, Role role, Flight arrFlight)
        {
            var webfarm = ConfigureWebFarmNodeDefaults(webFarmsCollection, arrFlight.GetEffectiveRedirectBase(role));
            var webfarmCollection = webfarm.GetCollection();
            CreateWebFarmServers(arrFlight.Target, webfarmCollection);
            webFarmsCollection.Add(webfarm);
        }

        internal static void CreateWebFarm(ConfigurationElementCollection webFarmsCollection, Role role)
        {
            var webfarm = ConfigureWebFarmNodeDefaults(webFarmsCollection, role.GetEffectiveRedirectBase());
            var webfarmCollection = webfarm.GetCollection();
            CreateWebFarmServers(role.Target, webfarmCollection);
            webFarmsCollection.Add(webfarm);
        }  

        static ConfigurationElement ConfigureWebFarmNodeDefaults(ConfigurationElementCollection webFarmsCollection, string webfarmName)
        {
            //get a handle to the webfarm or create if it does not already exist
            ConfigurationElement webfarm = webFarmsCollection.FirstOrDefault(element => webfarmName == (element["name"] as string))
                            ?? webFarmsCollection.CreateElement("webFarm");

            webfarm["name"] = webfarmName;
            webfarm["enabled"] = true;

            //configure default ARR settings for routing, cache, protocol and client affinity
            var webfarmCollection = webfarm.GetCollection();

            var webfarmARRSettings = webfarmCollection.GetChildElement("applicationRequestRouting");
            var protocol = webfarmARRSettings.GetChildElement("protocol");
            protocol["httpVersion"] = "PassThrough";
            protocol["reverseRewriteHostInResponseHeaders"] = true;
            protocol["preserveHostHeader"] = false;

            var cache = protocol.GetChildElement("cache");
            cache["enabled"] = false;
            cache["validationInterval"] = TimeSpan.FromMinutes(1); // default
            var loadBalancing = webfarmARRSettings.GetChildElement("loadBalancing");
            loadBalancing["algorithm"] = "WeightedRoundRobin";
            var affinity = webfarmARRSettings.GetChildElement("affinity");
            affinity["useCookie"] = true;
            affinity["cookieName"] = string.Format("ARRAffinity{0}", webfarmName);

            return webfarm;
        }

        static void CreateWebFarmServers(IEnumerable<TargetRoute> routes, ConfigurationElementCollection webfarmCollection)
        {
            foreach (var route in routes)
            {
                var server = webfarmCollection.CreateElement("server");
                server["address"] = route.Redirect; 
                server["enabled"] = true;
                var flightARR = server.GetChildElement("applicationRequestRouting");
                flightARR["weight"] = route.Weight ?? 100; //set to same default used by inetmgr                

                webfarmCollection.Add(server);
            }
        }      
    }
}
